use std::fs;
use std::path::Path;
use anyhow::Result;
use log::debug;
use roxmltree::Document;
use crate::project::Project;

pub struct ProjectParser {
    pub project: Project,
}

impl ProjectParser {
    pub fn new(project: Project) -> Self {
        Self { project }
    }

    pub fn parse_vcxproj(&mut self, vcxproj_path: &Path) -> Result<()> {
        let content = fs::read_to_string(vcxproj_path)?;
        let doc = Document::parse(&content)?;
        
        // Parse project configurations
        self.parse_project_configurations(&doc)?;
        
        // Parse Qt modules
        self.parse_qt_modules(&doc)?;
        
        // Parse source files
        self.parse_source_files(&doc)?;
        
        // Parse header files
        self.parse_header_files(&doc)?;
        
        // Parse Qt resource files
        self.parse_qt_resources(&doc)?;
        
        // Parse Qt UI files
        self.parse_qt_forms(&doc)?;
        
        // Parse libraries
        self.parse_libraries(&doc)?;
        
        // Parse preprocessor definitions
        self.parse_preprocessor_defs(&doc)?;
        
        // Parse dependencies
        self.parse_dependencies(&doc)?;
        
        // Parse include directories
        self.parse_include_directories(&doc)?;
        
        Ok(())
    }

    fn parse_project_configurations(&mut self, doc: &Document) -> Result<()> {
        // 解析项目配置，如Debug/Release等
        for node in doc.descendants() {
            if node.tag_name().name() == "ProjectConfiguration" {
                if let Some(include) = node.attribute("Include") {
                    // 这里可以保存配置信息，如果需要的话
                    debug!("Found project configuration: {}", include);
                }
            }
        }
        Ok(())
    }

    fn parse_qt_modules(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "QtModules" {
                if let Some(modules) = node.text() {
                    // 解析Qt模块，格式如：core;gui;widgets
                    self.project.qt_modules = modules
                        .split(';')
                        .map(|s| s.trim().to_string())
                        .collect();
                }
            }
        }
        Ok(())
    }

    fn parse_source_files(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "ClCompile" {
                if let Some(include) = node.attribute("Include") {
                    // 只添加.cpp文件
                    if include.ends_with(".cpp") {
                        self.project.source_files.push(include.to_string());
                    }
                }
            }
        }
        Ok(())
    }

    fn parse_header_files(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "ClInclude" || node.tag_name().name() == "QtMoc" {
                if let Some(include) = node.attribute("Include") {
                    // 添加.h文件
                    if include.ends_with(".h") {
                        self.project.header_files.push(include.to_string());
                    }
                }
            }
        }
        Ok(())
    }

    fn parse_qt_resources(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "QtRcc" {
                if let Some(include) = node.attribute("Include") {
                    self.project.resources.push(include.to_string());
                }
            }
        }
        Ok(())
    }

    fn parse_qt_forms(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "QtUic" {
                if let Some(include) = node.attribute("Include") {
                    self.project.forms.push(include.to_string());
                }
            }
        }
        Ok(())
    }

    fn parse_libraries(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "AdditionalDependencies" {
                if let Some(libs) = node.text() {
                    // 解析库文件，格式如：lib1.lib;lib2.lib
                    self.project.libraries = libs
                        .split(';')
                        .map(|s| s.trim().to_string())
                        .collect();
                }
            }
        }
        Ok(())
    }

    fn parse_preprocessor_defs(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "PreprocessorDefinitions" {
                if let Some(defs) = node.text() {
                    // 获取当前配置（Debug/Release）
                    let config = node
                        .ancestors()
                        .find(|n| n.tag_name().name() == "PropertyGroup")
                        .and_then(|n| n.attribute("Condition"))
                        .unwrap_or("Debug");

                    // 解析预处理器定义，格式如：_DEBUG;WIN32;_WINDOWS
                    let definitions = defs
                        .split(';')
                        .map(|s| s.trim().to_string())
                        .collect();

                    self.project.preprocessor_defs.insert(config.to_string(), definitions);
                }
            }
        }
        Ok(())
    }

    fn parse_dependencies(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "ProjectReference" {
                if let Some(include) = node.attribute("Include") {
                    // 从项目引用路径中提取项目名称
                    if let Some(name) = include.split('\\').last() {
                        self.project.dependencies.push(name.to_string());
                    }
                }
            }
        }
        Ok(())
    }

    fn parse_include_directories(&mut self, doc: &Document) -> Result<()> {
        for node in doc.descendants() {
            if node.tag_name().name() == "AdditionalIncludeDirectories" {
                if let Some(includes) = node.text() {
                    // 获取当前配置（Debug/Release）
                    let config = node
                        .ancestors()
                        .find(|n| n.tag_name().name() == "ItemDefinitionGroup")
                        .and_then(|n| n.attribute("Condition"))
                        .map(|cond| {
                            if cond.contains("Debug") {
                                "Debug"
                            } else {
                                "Release"
                            }
                        })
                        .unwrap_or("Debug");

                    // 解析包含目录，格式如：dir1;dir2;%(AdditionalIncludeDirectories)
                    let dirs = includes
                        .split(';')
                        .filter(|s| !s.starts_with("%(")) // 过滤掉宏
                        .map(|s| s.trim().to_string())
                        .collect();

                    self.project.include_directories.insert(config.to_string(), dirs);
                }
            }
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::PathBuf;

    #[test]
    fn test_parse_qt_widgets_project() {
        // 创建测试项目
        let project = Project::new("QtWidgetsForTest".to_string());
        let mut parser = ProjectParser::new(project);

        // 获取测试项目文件路径
        let vcxproj_path = PathBuf::from("test_projects/vs_qt_project/QtWidgetsForTest/QtWidgetsForTest/QtWidgetsForTest.vcxproj");
        
        // 解析项目文件
        let result = parser.parse_vcxproj(&vcxproj_path);
        assert!(result.is_ok(), "Failed to parse vcxproj file");

        // 验证 Qt 模块
        assert_eq!(parser.project.qt_modules, vec!["core", "gui", "widgets"]);

        // 验证源文件
        assert!(parser.project.source_files.contains(&"QtWidgetsForTest.cpp".to_string()));
        assert!(parser.project.source_files.contains(&"main.cpp".to_string()));
        assert!(parser.project.source_files.contains(&"person\\person.cpp".to_string()));

        // 验证头文件
        assert!(parser.project.header_files.contains(&"QtWidgetsForTest.h".to_string()));
        assert!(parser.project.header_files.contains(&"person\\person.h".to_string()));

        // 验证 Qt 资源文件
        assert!(parser.project.resources.contains(&"QtWidgetsForTest.qrc".to_string()));

        // 验证 Qt UI 文件
        assert!(parser.project.forms.contains(&"QtWidgetsForTest.ui".to_string()));
        
        // 验证包含目录
        let include_dirs = parser.project.include_directories.get("Debug");
        assert!(include_dirs.is_some());
        let include_dirs = include_dirs.unwrap();
        assert!(include_dirs.contains(&"person".to_string()));
    }
} 